---
title: Register and Login User with Password in a Custom Login UI
sidebar_label: Username and Password
---

## Flow

![Register and Login Flow](/img/guides/login-ui/username-password-flow.png)

## Register

First, we create a new user with a username and password. In the example below we add a user with profile data, a verified email address, and a password.
[Create User Documentation](/apis/resources/user_service_v2/user-service-add-human-user)

### Custom Fields

If you have custom fields you like to add to your users that are not provided by ZITADEL, you can add them to the metadata.
Metadata are key value pairs you can use for additional user data.
These fields can also be included in the token of the user, so you have access to it all the time.
Read more about the metadata [here](/docs/guides/manage/customize/user-metadata)

### Request

```bash
curl --request POST \
  --url https://${CUSTOM_DOMAIN}/v2/users/human \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer '"$TOKEN"'' \
  --header 'Content-Type: application/json' \
  --data '{
  "userId": "d654e6ba-70a3-48ef-a95d-37c8d8a7901a",
  "username": "minnie-mouse",
  "profile": {
    "givenName": "Minnie",
    "familyName": "Mouse",
    "nickName": "Mini",
    "displayName": "Minnie Mouse",
    "preferredLanguage": "en",
    "gender": "GENDER_FEMALE"
  },
  "email": {
    "email": "mini@mouse.com",
    "isVerified": true
  },
  "metadata": [
    {
      "key": "my-key",
      "value": "VGhpcyBpcyBteSB0ZXN0IHZhbHVl"
    }
  ],
  "password": {
    "password": "Secr3tP4ssw0rd!",
    "changeRequired": false
  }
}'
```

### Response

```bash
{
	"userId": "d654e6ba-70a3-48ef-a95d-37c8d8a7901a",
	"details": {
		"sequence": "570",
		"changeDate": "2023-06-13T12:44:36.967851Z",
		"resourceOwner": "163840776835432705"
	}
}
```

If you want the user to verify the email address you can either choose that ZITADEL sends a verification email to the user by adding a urlTemplate into the sendCode, or ask for a return code to send your own emails.

Send Email by ZITADEL:

```bash
"sendCode": {
  "urlTemplate": "https://example.com/email/verify?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}"
},
```

Return Code:
```bash
"email": {
    "email": "mini@mouse.com",
    "returnCode": {}
},
```

To check what is allowed on your instance, call the settings service for more information.
The following requests can be useful for registration:
- [Get Login Settings](/apis/resources/settings_service_v2/settings-service-get-login-settings) To find out which authentication possibilities are enabled (password, identity provider, etc.)
- [Get Password Complexity Settings](/apis/resources/settings_service_v2/settings-service-get-password-complexity-settings) to find out how the password should look like (length, characters, etc.)

## Create Session with User Check

After you have created a new user, you can redirect them to your login screen.
You can either create a new empty session as soon as the first login screen is shown or update it with each piece of information you get throughout the process.
Or you can create a new session with the first credentials a user enters.
In the following example, we assume that the login flow asks for the username in the first step, and in the second for the password.
In API requests, this means creating a new session with a username and updating it with the password.
If you already have the userId from a previous register, you can send it directly to skip the username and show the password screen directly.
The create and update session endpoints will always return a session ID and an opaque session token.
If you do not rely on the OIDC standard you can directly use the token.
Send it to the Get Session Endpoint to find out how the user has authenticated.

- [Create new session Documentation](/apis/resources/session_service_v2/session-service-create-session)
- [Update an existing session Documentation](/apis/resources/session_service_v2/session-service-set-session)
- [Get Session Documentation](/apis/resources/session_service_v2/session-service-get-session)

### Request

```bash
curl --request POST \
  --url https://${CUSTOM_DOMAIN}/v2/sessions \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer '"$TOKEN"'' \
  --header 'Content-Type: application/json' \
  --data '{
  "checks": {
    "user": {
      "loginName": "minnie-mouse@fabi.zitadel.app"
    }
  }
}'
```

### Response

```bash
{
	"details": {
		"sequence": "580",
		"changeDate": "2023-06-14T05:32:39.007096Z",
		"resourceOwner": "163840776835432705"
	},
	"sessionId": "218480890961985793",
	"sessionToken": "yMDi6uVPJAcphbbz0LaxC07ihWkNTe7m0Xqch8SzfM5Cz3HSIQIDZ65x1f5Qal0jxz0MEyo-_zYcUg"
}
```

### Session State

If you read the newly created session, it will look like the following.
You can see the creation and change date.
In the factors, you will see all the checks that have been made.
In this case, the user has been checked.

```bash
{
	"session": {
		"id": "218480890961985793",
		"creationDate": "2023-06-14T05:32:38.977954Z",
		"changeDate": "2023-06-14T05:32:39.007096Z",
		"sequence": "580",
		"factors": {
			"user": {
				"verifiedAt": "2023-06-14T05:32:38.972712Z",
				"id": "d654e6ba-70a3-48ef-a95d-37c8d8a7901a",
				"loginName": "minnie-mouse@fabi.zitadel.app",
				"displayName": "Minnie Mouse"
			}
		}
	}
}
```

Checkout how to handle [session validation](./session-validation).

## Update Session with Password

Your session already has a username check.
The next step is to check the password.
To update an existing session, add the session ID you got in the previous step to the URL.

### Request

```bash
curl --request PATCH \
  --url https://${CUSTOM_DOMAIN}/v2/sessions/$SESSION_ID \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer '"$TOKEN"''\
  --header 'Content-Type: application/json' \
  --data '{
  "checks": {
    "password": {
      "password": "Secr3tP4ssw0rd!"
    }
  }
}'
```

### Response

The response of the create and update session token looks the same.
Make sure to always use the session token of the last response you got, as the values may be updated.

```bash
{
	"details": {
		"sequence": "582",
		"changeDate": "2023-06-14T05:42:11.631901Z",
		"resourceOwner": "163840776835432705"
	},
	"sessionToken": "blGKerGQPKv8jN21p6E9GB1B-vl6_EyKlvTd5UALu8-aQmjucgZxHSXJx3XMFTwT9_Y3VnbOo3gC_Q"
}
```

### Session State
If you read your session after the password check, you will see that the check has been added to the factors with the verification date.

```bash
{
	"session": {
		"id": "218480890961985793",
		"creationDate": "2023-06-14T05:32:38.977954Z",
		"changeDate": "2023-06-14T05:42:11.631901Z",
		"sequence": "582",
		"factors": {
			"user": {
				"verifiedAt": "2023-06-14T05:32:38.972712Z",
				"id": "d654e6ba-70a3-48ef-a95d-37c8d8a7901a",
				"loginName": "minnie-mouse@fabi.zitadel.app",
				"displayName": "Minnie Mouse"
			},
			"password": {
				"verifiedAt": "2023-06-14T05:42:11.619484Z"
			}
		}
	}
}

```

## List the Sessions (Account Chooser)

import SelectAccount from './_select-account.mdx';

<SelectAccount/>

## Logout User

import Logout from './_logout.mdx';

<Logout/>
